#pragma once

#include "qbe/src/ecs/app.hpp"

#include <entt/entt.hpp>

#include "spdlog/spdlog.h"

#include "../utils/utils.hpp"

namespace qbe::observe {

// 实体增删改时回调，可在源文本中打断点以监控
void entityCreate(entt::registry& reg, entt::entity e);
void entityUpdate(entt::registry& reg, entt::entity e);
void entityDestry(entt::registry& reg, entt::entity e);

// 实体附加ComponentType组件时回调，直接打断点以监控
template <typename ComponentType>
void componentCreate_impl(entt::registry& reg, entt::entity e) {
  std::string info;

  info = "Observe add component: " + std::to_string((uint32_t)e) + "\n";
  info += std::string("    ComponentType:") + std::type_index(typeid(ComponentType)).name() + "\n";
  info += "    ElementType: " + getEntityNameOfCellElemnt(reg, e);

  SPDLOG_INFO(info);

  // assert(utils::entity_valid(reg, e) && "被选中实体必须包含内核组件");
}

/*
  Observe模块影响性能，仅在debug模式作为插件，
  不要在此处添加处理逻辑，否则release会失效。
*/

// 实体更新ComponentType组件时回调，直接打断点以监控
template <typename ComponentType>
void componentUpdate_imple(entt::registry& reg, entt::entity e) {
  std::string info;

  info = "Observe update component: " + std::to_string((uint32_t)e) + "\n";
  info += std::string("    ComponentType:") + std::type_index(typeid(ComponentType)).name() + "\n";
  info += "    ElementType: " + getEntityNameOfCellElemnt(reg, e);

  SPDLOG_INFO(info);
}

// 实体删除ComponentType组件时回调，直接打断点以监控
template <typename ComponentType>
void componentDestry_imple(entt::registry& reg, entt::entity e) {
  std::string info;

  info = "Observe delete component: " + std::to_string((uint32_t)e) + "\n";
  info += std::string("    ComponentType:") + std::type_index(typeid(ComponentType)).name() + "\n";
  info += "    ElementType: " + getEntityNameOfCellElemnt(reg, e);

  SPDLOG_INFO(info);
}

class Plugin : public ecs::Plugin {
 public:
  void build(ecs::App& app) override;
};

}  // namespace qbe::observe